package routes

import (
	"github.com/gin-contrib/sessions"
	"github.com/gin-contrib/sessions/cookie"
	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
	"github.com/go-playground/validator/v10"
	"github.com/sirupsen/logrus"
	"todo-list/api"
	"todo-list/middleware"
)

func NewRouter() *gin.Engine {
	r := gin.New()
	// 创建基于cookie的存储引擎, secret1111111 参数是用于加密的密钥
	store := cookie.NewStore([]byte("secret1111111"))
	// 设置session中间件，todo-list-session，指的是session的名字，也是cookie的名字
	// store是前面创建的存储引擎，可以替换成其他存储引擎
	r.Use(gin.Recovery())
	//跨域问题
	r.Use(middleware.CorsMiddleWare())
	r.Use(middleware.LogMiddleware())
	r.Use(sessions.Sessions("todo-list-session", store))

	// 设置自定义校验
	registerValidators(getValidators())
	noNeedAuthedApi := r.Group("/g0")
	needAuthedApi := r.Group("/g1")
	needAuthedApi.Use(middleware.AuthenticationMiddleWare())

	userG0Api := noNeedAuthedApi.Group("/user")
	userG1Api := needAuthedApi.Group("/user")
	taskG0Api := noNeedAuthedApi.Group("/task")
	taskG1Api := needAuthedApi.Group("/task")

	// 以下是无需鉴权的api
	// 公共的api
	{
		noNeedAuthedApi.GET("/ping", api.Ping)
		noNeedAuthedApi.GET("/taskStatus", api.ListTaskStatusHandler())
	}
	//用户相关的api
	{
		userG0Api.POST("/register", api.RegisterHandler())
		userG0Api.POST("/login", api.LoginHandler())
	}
	// 待办事项相关的api
	{
		taskG0Api.GET("/", api.ViewPublicTaskHandler())
		taskG0Api.GET("/:id", api.ShowTaskHandler())
	}
	// 以下是需要鉴权的api
	// 公共的api
	{
		needAuthedApi.GET("ping", api.Ping)
	}
	// 用户相关的api
	{
		userG1Api.GET("/logout", api.LogoutHandler())
	}
	// 待办事项相关的api
	{
		taskG1Api.GET("/", api.ViewSelfTaskHandler())
		taskG1Api.POST("/", api.CreateTaskHandler())
		taskG1Api.PUT("/:id", api.UpdateTaskHandler())
		taskG1Api.PATCH("/", api.UpdateTaskStatusOrPublicBatchHandler())
	}
	return r
}

func registerValidators(validators map[string]validator.Func) {
	if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
		for tag, handler := range validators {
			err := v.RegisterValidation(tag, handler)
			if err != nil {
				logrus.Errorf("RegisterValidation")
			}
		}

	} else {
		logrus.Errorln("get binding validator engine fail")
	}
}
